#include "MySQLClient.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <crypt.h>
#include <string>
#include <cstring>
#include <iostream>
#include <sstream>
using namespace std;
myNameSpace::MySQLClient mysqlClient;
using namespace myNameSpace;
string genRandomSalt(size_t length = 8) // 生成一个指定长度的随机盐值
{
    const char *prefix = "$1$"; // MD5 加密前缀
    char output[128];
    // 使用crypt_gensalt_rn函数（线程安全版本）
    if (crypt_gensalt_rn(prefix, 0, NULL, length, output, sizeof(output)) == NULL)
    {
        perror("crypt_gensalt_rn");
        return "";
    }
    return string(output);
}

string registerClient(const string &client_name,
                      const string &client_salt,
                      const string &client_encrypt) // 给指定用户添加数据
{
    char buffer[200]; // 确保缓冲区足够大！
    sprintf(buffer, "insert into monitor_client (client_name) VALUES('%s');", client_name.c_str());
    mysqlClient.writeOperationQuery(string(buffer));
    string salt = "'" + client_salt + "'";
    string encrypt = "'" + client_encrypt + "'";
    mysqlClient.appendData("monitor_client", "client_setting", salt, "client_name", client_name);
    mysqlClient.appendData("monitor_client", "client_encrypt", encrypt, "client_name", client_name);
    return "";
}

string createEncrypt(string password, string salt)
{
    // 此函数运行在服务器上，客户端由Qt生成encrypt
    //  通过密码和盐值生成加密密文，保存到服务器数据库

    // 1. 在栈上分配工作缓冲区
    struct crypt_data data;
    // 2. ！！！关键：初始化缓冲区，将其内存清零
    bzero(&data, sizeof(data));

    // 3. 调用线程安全的 crypt_r
    char *result = crypt_r(password.c_str(), salt.c_str(), &data);

    if (result == NULL)
    {
        perror("crypt_r");
        return "";
    }
    string res(result);
    return res;
}

bool isCodeSame(string encrypClient, string encryptSQL)
{
    // todo这个
    // encrypClient是客户二次计算后得到密文，发送给服务器
    // ncryptSQL是加密密文，存储在服务器上，此处需要从数据库取出
    return encryptSQL == encrypClient;
}

int main()
{
    mysqlClient.connect("localhost", "root", "580231", "smart_monitor_system", 0);
    string tableName = "monitor_client";

    while (1)
    {
        string client_name, cilent_password;
        cout << "请输入账户名和密码" << endl;
        cin >> client_name;
        cout << "请输入密码" << endl;
        cin >> cilent_password;

        string res = mysqlClient.findData(tableName, "client_name", "client_name", "'" + client_name + "'");
        if (res == "")
        {
            cout << "用户不存在，注册？" << endl;
            cout << "此处Qt界面需要一个注册按钮" << endl;

            // 该盐值获取函数，应该服务器提供，并且保存下来
            string client_salt = genRandomSalt();

            // 该加密密文获取函数，客户端提供，
            string client_encrypt = createEncrypt(cilent_password, client_salt);

            // 在客户注册阶段二，接收到客户发送过来密文时，才能进行实际注册，写入数据库
            registerClient(client_name, client_salt, client_encrypt);
            cout << "注册完成" << endl;
        }
        else
        {
            cout << "用户存在" << endl;
            string client_salt = mysqlClient.findData(tableName, "client_setting", "client_name", "'" + client_name + "'");
            string client_encrypt_server = mysqlClient.findData(tableName, "client_encrypt", "client_name", "'" + client_name + "'");
            string client_encrypt_local = createEncrypt(cilent_password, client_salt);
            cout << client_encrypt_server << endl;
            cout << client_encrypt_local << endl;
            if (client_encrypt_local == client_encrypt_server)
            {
                cout << "密码正确" << endl;
                break;
            }
            else
            {
                cout << "密码错误" << endl;
                // TO DO最多尝试输入3次密码
            }
        }
    }
}

/* int main(int argc, char *argv[]) */
/* { */
/*     string setting = genRandomSalt(8); */
/*     cout << setting << endl; */
/*     cout << "请输入新用户密码" << endl; */
/*     string password; */
/*     cin >> password; */

/*     string Encrypt = createEncrypt(password, setting); */
/*     cout << Encrypt << endl; */

/*     while (1) */
/*     { */
/*         string mima; */
/*         cout << "请输入验证密码" << endl; */
/*         cin >> mima; */
/*         bool issame = isCodeSame(createEncrypt(mima, setting), Encrypt); */
/*         if (issame) */
/*             cout << "密码正确" << endl; */
/*         else */
/*             cout << "密码错误" << endl; */
/*     } */

/*     return 0; */
/* } */
